
import { toReactive } from './reactive.js';
import { toRaw, isReadonly, isShallow, hasChanged, isRef } from './utils.js'
class RefImpl {
	constructor(value, __v_isShallow) {
		this.__v_isShallow = __v_isShallow;
		this.dep = undefined;
		this.__v_isRef = true;
		this._rawValue = __v_isShallow ? value : toRaw(value);
		this._value = __v_isShallow ? value : toReactive(value);
	}
	get value() {
		console.log(`output->value`,666)
		trackRefValue(this);
		return this._value;
	}
	set value(newVal) {
		const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
		newVal = useDirectValue ? newVal : toRaw(newVal);
		if (hasChanged(newVal, this._rawValue)) {
			this._rawValue = newVal;
			this._value = useDirectValue ? newVal : toReactive(newVal);
			triggerRefValue(this, newVal);
		}
	}
}
function triggerEffect(effect, debuggerEventExtraInfo) {
	if (effect !== activeEffect || effect.allowRecurse) {
		if (effect.onTrigger) {
			effect.onTrigger(extend({ effect }, debuggerEventExtraInfo));
		}
		if (effect.scheduler) {
			effect.scheduler();
		}
		else {
			effect.run();
		}
	}
}
function triggerEffects(dep, debuggerEventExtraInfo) {
	// spread into array for stabilization
	const effects = isArray(dep) ? dep : [...dep];
	for (const effect of effects) {
		if (effect.computed) {
			triggerEffect(effect, debuggerEventExtraInfo);
		}
	}
	for (const effect of effects) {
		if (!effect.computed) {
			triggerEffect(effect, debuggerEventExtraInfo);
		}
	}
}
function triggerRefValue(ref, newVal) {
	ref = toRaw(ref);
	const dep = ref.dep;
	if (dep) {
		{
			triggerEffects(dep, {
				target: ref,
				type: "set" /* TriggerOpTypes.SET */,
				key: 'value',
				newValue: newVal
			});
		}
	}
}
let activeEffect;
let shouldTrack = true;
let effectTrackDepth = 0;
let trackOpBit = 1;
/**
 * The bitwise track markers support at most 30 levels of recursion.
 * This value is chosen to enable modern JS engines to use a SMI on all platforms.
 * When recursion depth is greater, fall back to using a full cleanup.
 */
const maxMarkerBits = 30;
const wasTracked = (dep) => (dep.w & trackOpBit) > 0;
const newTracked = (dep) => (dep.n & trackOpBit) > 0;
function trackEffects(dep, debuggerEventExtraInfo) {
	let shouldTrack = false;
	if (effectTrackDepth <= maxMarkerBits) {
		if (!newTracked(dep)) {
			dep.n |= trackOpBit; // set newly tracked
			shouldTrack = !wasTracked(dep);
		}
	}
	else {
		// Full cleanup mode.
		shouldTrack = !dep.has(activeEffect);
	}
	if (shouldTrack) {
		dep.add(activeEffect);
		activeEffect.deps.push(dep);
		if (activeEffect.onTrack) {
			activeEffect.onTrack(Object.assign({ effect: activeEffect }, debuggerEventExtraInfo));
		}
	}
}
const createDep = (effects) => {
	const dep = new Set(effects);
	dep.w = 0;
	dep.n = 0;
	return dep;
};

function trackRefValue(ref) {
	console.log(shouldTrack, activeEffect)
	if (shouldTrack && activeEffect) {
		ref = toRaw(ref);
	console.log(`output->ref`,ref)
		{
			trackEffects(ref.dep || (ref.dep = createDep()), {
				target: ref,
				type: "get" /* TrackOpTypes.GET */,
				key: 'value'
			});
		}
	}
}
function createRef(rawValue, shallow) {
	if (isRef(rawValue)) {
		return rawValue;
	}
	return new RefImpl(rawValue, shallow);
}
export function ref(value) {
	return createRef(value, false);
}